<script setup lang="ts">
import { Page, useVbenModal } from '@vben/common-ui';
import { useRoute } from 'vue-router';
import { computed, ref, onMounted } from 'vue';
import {
  Layout,
  Select,
  Button,
  Space,
  Input,
  InputNumber,
  Card,
  message,
  Popconfirm,
  Switch,
  Divider,
  theme,
} from 'ant-design-vue';
import {
  FormOutlined,
  DeleteOutlined,
  ClockCircleOutlined,
  AppstoreAddOutlined,
} from '@ant-design/icons-vue';
import draggable from 'vuedraggable';
import {
  planCycleAdd,
  planCycleUpdate,
  planCycleRemove,
} from '#/api/healthPlan/config/planCycle';
import type {
  PeriodType,
  PlanCycleVO,
} from '#/api/healthPlan/config/planCycle/model';
import { templateDetail } from '#/api/healthPlan/template';
import type {
  PlanConfigForm,
  PlanConfigVO,
} from '#/api/healthPlan/config/planConfig/model';
import {
  planConfigAdd,
  planConfigRemove,
} from '#/api/healthPlan/config/planConfig';
import { planContentOptions } from '@vben/constants';
import followUpModal from './components/followUp-modal.vue';
import monitorModal from './components/monitor-modal.vue';
import educationModal from './components/education-modal.vue';
import visitModal from './components/visit-modal.vue';
import exerciseModal from './components/exercise-modal.vue';
import medicationModal from './components/medication-modal.vue';
import dietModal from './components/diet-modal.vue';
import knowledgeModal from './components/knowledge-modal.vue';

const { token } = theme.useToken();

// vuedraggable 的事件类型定义
interface DraggableEndEvent {
  to: HTMLElement;
  item: HTMLElement;
}

interface DraggableAddEvent<T> {
  element: T;
  item: any;
  newIndex: number;
}

interface Periodoptions {
  label: string;
  value: PeriodType;
}

const route = useRoute();
import { useTabs } from '@vben/hooks';

const planId = route.params.id as string;
const planName = route.params.planName as string;
const { setTabTitle } = useTabs();
setTabTitle(`${planName}-方案配置`);

// --- Modals & Drawers ---
const [FollowUpModal, followUpModalApi] = useVbenModal({
  connectedComponent: followUpModal,
});
const [EducationModal, educationModalApi] = useVbenModal({
  connectedComponent: educationModal,
});
const [MonitorModal, monitorModalApi] = useVbenModal({
  connectedComponent: monitorModal,
});
const [ExerciseModal, exerciseModalApi] = useVbenModal({
  connectedComponent: exerciseModal,
});
const [MedicationModal, medicationModalApi] = useVbenModal({
  connectedComponent: medicationModal,
});
const [DietModal, dietModalApi] = useVbenModal({
  connectedComponent: dietModal,
});
const [VisitModal, visitModalApi] = useVbenModal({
  connectedComponent: visitModal,
});
const [KnowledgeModal, knowledgeModalApi] = useVbenModal({
  connectedComponent: knowledgeModal,
});

// 控制左右
const layoutDirection = ref(true); // true: ltr, false: rtl

// 2. 研究周期 (cycleList)
const cycleList = computed<PlanCycleVO[]>(() => planDetail.value ?? []);

// 4. 全局单位设置
const cycleUnit = ref<PeriodType>('天');

const unitOptions: Periodoptions[] = [
  { label: '天', value: '天' },
  { label: '周', value: '周' },
  { label: '月', value: '月' },
];

const planDetail = ref<PlanCycleVO[] | null>(null);

// 获取方案详情--List数组格式
const getPlanDetail = async (planId: string) => {
  planDetail.value = await templateDetail(planId);
  if (planDetail.value?.length) {
    cycleUnit.value = planDetail.value[0]!.cycleUnit;
  }
};

const refresh = async () => {
  await getPlanDetail(planId);
  message.success('方案详情已刷新');
};

const addPeriodDbClick = async () => {
  // 校验逻辑：检查最后一个周期是否已填写完整
  const lastPeriod: PlanCycleVO | undefined =
    cycleList.value[cycleList.value.length - 1];
  if (lastPeriod && cycleList.value.length > 0) {
    if (!lastPeriod.nodeName || !lastPeriod.startDay || !lastPeriod.endDay) {
      message.warning('请先完成上一个周期的所有项目再添加新周期');
      return;
    }
  }
  await addPeriod(cycleList.value.length);
};

// 添加周期
const addPeriod = async (newIndex: number) => {
  try {
    const data = {
      planId,
      cycleUnit: cycleUnit.value,
    };
    const newId = await planCycleAdd(data);
    cycleList.value.splice(newIndex, 0, {
      planId,
      cycleUnit: cycleUnit.value,
      id: newId,
      nodeName: '',
      startDay: undefined,
      endDay: undefined,
      reminders: [],
    });
    message.success('已添加新周期，请手动输入时间并保存');
    // 新增成功后，重新获取整个列表以保证数据同步
  } catch (error) {
    console.error('Failed to add period:', error);
    await getPlanDetail(planId);
  }
};

const updPeriod = async (period: PlanCycleVO, currentIndex: number) => {
  // 验证周期天数不能小于1
  if ((period.startDay && period.startDay < 1) || (period.endDay && period.endDay < 1)) {
    message.warning('周期天数不能小于1');
    return;
  }

  // 保存前校验
  if (!period.nodeName || !period.startDay || !period.endDay) {
    message.warning('请填写完整的周期信息后再保存');
    return;
  }

  // 1. 行内校验：结束日必须大于开始日
  if (period.endDay <= period.startDay) {
    message.warning('结束日期必须大于开始日期');
    period.endDay = undefined; // 清空错误值
    return;
  }
  // 2. 行间校验：与前后周期不能重叠
  // 检查与上一个周期的关系
  if (currentIndex > 0) {
    const prevPeriod = cycleList.value[currentIndex - 1];
    if (period.startDay <= prevPeriod!.endDay!) {
      message.warning(
        `开始日期必须大于上一个周期的结束日期 (${prevPeriod!.endDay})`,
      );
      period.startDay = undefined; // 清空错误值
      period.endDay = undefined; // 清空错误值
      return;
    }
  }

  // 检查与下一个周期的关系
  if (currentIndex < cycleList.value.length - 1) {
    const nextPeriod = cycleList.value[currentIndex + 1];
    if (period.endDay >= nextPeriod!.startDay!) {
      message.warning(
        `结束日期必须小于下一个周期的开始日期 (${nextPeriod!.startDay})`,
      );
      period.startDay = undefined; // 清空错误值
      period.endDay = undefined; // 清空错误值
      return;
    }
  }

  try {
    const healthPlanCycleBo = {
      ...period,
      nodeName: period.nodeName,
    };
    await planCycleUpdate(healthPlanCycleBo);
  } catch (error) {
    console.error('Failed to update period:', error);
    await getPlanDetail(planId);
  }
};

const delPeriod = async (periodId: string | number, periodIdx: number) => {
  try {
    if (cycleList.value[periodIdx]?.reminders?.length) {
      return message.error('该周期下存在任务，请先删除任务');
    }
    await planCycleRemove(periodId);
    await getPlanDetail(planId); // 重新获取列表以刷新
  } catch (error) {
    await getPlanDetail(planId); // 重新获取列表以刷新
    console.error('Failed to delete period:', error);
  }
};

const onPeriodDragAdd = async (event: DraggableAddEvent<any>) => {
  const { newIndex } = event;

  // --- 即时校验逻辑 ---
  const prevPeriod = newIndex > 0 ? cycleList.value[newIndex - 1] : null; //上一条
  const nextPeriod =
    newIndex < cycleList.value.length ? cycleList.value[newIndex] : null; //下一条

  // 校验上一个周期是否存在且完整
  if (
    prevPeriod &&
    (!prevPeriod.nodeName || !prevPeriod.startDay || !prevPeriod.endDay)
  ) {
    message.warning('请先完成并保存前一个周期的配置');
    return;
  }

  // 校验下一个周期是否存在且完整 (如果它存在的话)
  if (
    nextPeriod &&
    (!nextPeriod.nodeName || !nextPeriod.startDay || !nextPeriod.endDay)
  ) {
    message.warning('请先完成并保存后一个周期的配置');
    return;
  }

  if (newIndex === 0 && nextPeriod && nextPeriod.startDay! < 3) {
    message.warning('没有足够的时间间隔来插入新周期');
  }
  // 校验中间是否有足够的插入空间
  if (prevPeriod && nextPeriod) {
    if (nextPeriod.startDay! - prevPeriod.endDay! < 2) {
      message.warning('没有足够的时间间隔来插入新周期');
      return;
    }
  }
  await addPeriod(newIndex);
};

// 拖拽结束事件
function onDragEnd(event: DraggableEndEvent): void {
  console.log(event);
}

// 禁止组内拖拽
const onDragMove = () => {
  return false;
};

// 从左侧新添加到右侧
const onDragAdd = async (
  event: DraggableAddEvent<{ label: string; value: string }>,
  periodIdx: number,
) => {
  const newItem = event.item._underlying_vm_;
  const period = cycleList.value[periodIdx];
  if (!period) return;

  // 校验：确保目标周期是已定义的
  if (!period.nodeName || !period.startDay || !period.endDay) {
    message.warning('无法添加到未保存或信息不完整的周期中');
    return;
  }
  try {
    const data: PlanConfigForm = {
      cycleId: period.id,
      taskName: newItem.label,
      taskType: newItem.value,
      triggerType: 'RELATIVE_TO_CYCLE',
      triggerConfig: {},
      taskConfig: {},
    };
    const newTaskId = await planConfigAdd(data);
    const newTask: PlanConfigVO = {
      id: newTaskId,
      cycleId: period.id,
      taskName: newItem.label,
      taskType: newItem.value,
      triggerType: 'RELATIVE_TO_CYCLE',
      triggerConfig: {},
      taskConfig: {},
    };
    cycleList.value[periodIdx]!.reminders.push(newTask);
  } catch (error) {
    console.error('Failed to add task:', error);
    await getPlanDetail(planId);
  }
};

const openTaskModal = (task: PlanConfigVO, period: PlanCycleVO) => {
  const cycleData = [period.startDay, period.endDay];
  // 未来可以根据 task.taskType 打开不同的弹窗
  switch (task.taskType) {
    case 'FOLLOW_UP':
      followUpModalApi.setData({ ...task, cycleData });
      followUpModalApi.open();
      break;
    case 'PATIENT':
      educationModalApi.setData({ ...task, cycleData });
      educationModalApi.open();
      break;
    case 'DAILY_TASK':
      monitorModalApi.setData({ ...task, cycleData });
      monitorModalApi.open();
      break;
    case 'EXERCISE':
      exerciseModalApi.setData({ ...task, cycleData });
      exerciseModalApi.open();
      break;
    case 'MEDICATION':
      medicationModalApi.setData({ ...task, cycleData });
      medicationModalApi.open();
      break;
    case 'DIET':
      dietModalApi.setData({ ...task, cycleData });
      dietModalApi.open();
      break;
    case 'VISIT':
      visitModalApi.setData({ ...task, cycleData });
      visitModalApi.open();
      break;
    case 'EDUCATION':
      knowledgeModalApi.setData({ ...task, cycleData });
      knowledgeModalApi.open();
      break;
    default:
      message.info('该任务类型暂无配置弹窗');
  }
};

const delPlanTask = async (taskId: string | number, periodIdx: number) => {
  try {
    await planConfigRemove(taskId);
    // 成功后前端控制删除
    cycleList.value[periodIdx]!.reminders = cycleList.value[
      periodIdx
    ]!.reminders.filter((task) => task.id !== taskId);
  } catch (error) {
    console.error('Failed to delete task:', error);
    await getPlanDetail(planId);
  }
};

onMounted(async () => {
  await getPlanDetail(planId);
});
</script>

<template>
  <Page :auto-content-height="true">
    <Layout
      has-sider
      class="bg-background h-full overflow-hidden rounded-lg"
      :style="{ flexDirection: layoutDirection ? 'row' : 'row-reverse' }"
    >
      <!-- 左侧/右侧方案内容 -->
      <Layout.Sider
        theme="light"
        :class="['p-4', layoutDirection ? 'border-r' : 'border-l']"
      >
        <div class="mb-4 flex items-center justify-between">
          <Space>
            <h3 class="text-md font-semibold">操作栏</h3>
            <Switch
              v-model:checked="layoutDirection"
              checked-children="左侧"
              un-checked-children="右侧"
            />
          </Space>
        </div>

        <Divider dashed />

        <h3 class="mb-2 text-base font-semibold">周期管理</h3>
        <div class="draggable-group">
          <draggable
            :model-value="[{ name: '时间点', type: 'period' }]"
            :group="{ name: 'periods', pull: 'clone', put: false }"
            :sort="false"
            item-key="type"
          >
            <template #item="{ element }">
              <div
                class="draggable-item bg-secondary border"
                @dblclick="addPeriodDbClick"
              >
                <ClockCircleOutlined />
                <span class="ml-2">{{ element.name }}</span>
              </div>
            </template>
          </draggable>
        </div>

        <Divider dashed />

        <h3 class="mb-2 text-base font-semibold">方案内容</h3>
        <div class="draggable-group">
          <draggable
            :model-value="planContentOptions"
            :group="{ name: 'tasks', pull: 'clone', put: false }"
            :sort="false"
            item-key="value"
          >
            <template #item="{ element }">
              <div class="draggable-item bg-secondary border">
                <AppstoreAddOutlined />
                <span class="ml-2">{{ element.label }}</span>
              </div>
            </template>
          </draggable>
        </div>
      </Layout.Sider>

      <!-- 右侧主配置区 -->
      <Layout.Content class="overflow-y-auto p-3">
        <!-- 研究周期定义 -->
        <div class="mb-6 rounded-md border p-3">
          <div class="mb-4 flex items-center justify-between">
            <div class="flex items-center">
              <h3 class="mr-4 text-lg font-semibold">研究周期</h3>
              <Space>
                <h3 class="mr-4 text-lg font-semibold">单位</h3>
                <Select
                  v-model:value="cycleUnit"
                  :options="unitOptions"
                  class="w-24"
                />
              </Space>
            </div>
            <Space>
              <Button @click="refresh">更新数据</Button>
            </Space>
          </div>
          <draggable
            :model-value="cycleList"
            group="periods"
            item-key="id"
            @add="onPeriodDragAdd"
            :move="onDragMove"
          >
            <template #item="{ element: period, index: periodIdx }">
              <div class="mb-2 flex items-center rounded p-2">
                <span class="mr-2">研究周期节点名称:</span>
                <Input v-model:value="period.nodeName" class="mr-4 w-40" />
                <span class="mr-2">第</span>
                <InputNumber
                  v-model:value="period.startDay"
                  :min="1"
                  class="w-20"
                />
                <span class="mx-2">至</span>
                <InputNumber
                  v-model:value="period.endDay"
                  :min="1"
                  class="mr-4 w-20"
                />
                <span>{{ cycleUnit }}</span>
                <Space class="ml-4">
                  <Button
                    type="primary"
                    size="small"
                    @click="updPeriod(period, periodIdx)"
                    >保存</Button
                  >
                  <Popconfirm
                    placement="right"
                    :title="`确认删除？${period.nodeName}?`"
                    @confirm="delPeriod(period.id, periodIdx)"
                  >
                    <Button type="primary" danger size="small">删除</Button>
                  </Popconfirm>
                </Space>
              </div>
            </template>
          </draggable>
        </div>

        <!-- 水平滚动任务区 -->
        <div class="overflow-x-auto pb-4 pl-5">
          <!-- 时间轴: 带起始和结束点 -->
          <div class="mb-4 flex items-center" style="height: 20px">
            <!-- 起始点 -->
            <div
              class="relative flex items-center justify-center"
              style="width: 1rem; min-width: 1rem; margin-left: -1rem"
            >
              <div
                class="absolute h-5 w-5 rounded-full bg-blue-200 opacity-50"
              ></div>
              <div class="absolute h-2 w-2 rounded-full bg-blue-500"></div>
            </div>

            <template v-for="() in cycleList">
              <!-- 1. 代表盒子空间的线 -->
              <div
                class="flex items-center"
                style="width: 200px; min-width: 200px"
              >
                <div class="h-px w-full bg-gray-300"></div>
              </div>

              <!-- 2. 代表间隙的点 -->
              <div
                class="relative flex items-center justify-center"
                style="width: 1rem; min-width: 1rem"
              >
                <div
                  class="absolute h-5 w-5 rounded-full bg-blue-200 opacity-50"
                ></div>
                <div class="absolute h-2 w-2 rounded-full bg-blue-500"></div>
              </div>
            </template>

            <!-- 结束点 (通过移除最后一个多余的点和线来实现) -->
            <div style="width: 200px; min-width: 200px"></div>
          </div>

          <div class="flex space-x-4">
            <!-- 单个周期盒子 -->
            <div
              v-for="(period, periodIdx) in cycleList"
              :key="`col-${period.id}`"
              class="bg-secondary rounded-lg border"
              style="width: 200px; min-width: 200px"
            >
              <!-- 盒子头部 -->
              <div
                class="bg-background rounded-t-lg border-b p-2 text-center font-semibold"
              >
                <div>{{ period.nodeName }}</div>
                <div class="text-xs text-gray-500">
                  {{
                    `第${period.startDay || '--'} 至 第${
                      period.endDay || '--'
                    }${cycleUnit}`
                  }}
                </div>
              </div>
              <!-- 盒子身体 (可拖拽区域) -->
              <draggable
                :model-value="period.reminders"
                group="tasks"
                item-key="id"
                class="min-h-[400px] p-2"
                :data-period-id="period.id"
                @end="onDragEnd"
                :move="onDragMove"
                @add="onDragAdd($event, periodIdx)"
              >
                <template #item="{ element }">
                  <Card
                    size="small"
                    class="mb-2 cursor-move"
                    :data-task-id="element.id"
                  >
                    <div class="flex flex-col">
                      <div class="flex items-center justify-between">
                        <span class="font-semibold">{{
                          element.taskConfig.reminderName || element.taskName
                        }}</span>
                        <Button
                          type="link"
                          size="small"
                          @click="openTaskModal(element, period)"
                        >
                          <FormOutlined />
                        </Button>
                      </div>
                      <div class="mt-2 flex items-center justify-between">
                        <span class="text-xs text-gray-400">{{
                          element.taskName
                        }}</span>
                        <Popconfirm
                          placement="left"
                          :title="`确认删除？${element.taskName}?`"
                          @confirm="delPlanTask(element.id, periodIdx)"
                        >
                          <Button type="link" size="small" danger>
                            <DeleteOutlined />
                          </Button>
                        </Popconfirm>
                      </div>
                    </div>
                  </Card>
                </template>
              </draggable>
            </div>
          </div>
        </div>
      </Layout.Content>
    </Layout>
    <FollowUpModal @reload="getPlanDetail(planId)" />
    <MonitorModal @reload="getPlanDetail(planId)" />
    <EducationModal @reload="getPlanDetail(planId)" />
    <ExerciseModal @reload="getPlanDetail(planId)" />
    <MedicationModal @reload="getPlanDetail(planId)" />
    <DietModal @reload="getPlanDetail(planId)" />
    <VisitModal @reload="getPlanDetail(planId)" />
    <KnowledgeModal @reload="getPlanDetail(planId)" />
  </Page>
</template>
<style scoped>
.draggable-item {
  display: flex;
  align-items: center;
  padding: 8px 12px;
  border-radius: 6px;
  margin-bottom: 8px;
  cursor: move;
  transition: all 0.2s ease-in-out;
}

.draggable-item:hover {
  background-color: v-bind('token.controlItemBgHover');
  border-color: v-bind('token.colorPrimary');
  color: v-bind('token.colorPrimary');
}
</style>
